package P7;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * 假设有一个客户端/服务器程序，为了提高性能，该客户端/服务器程序使用 Java NIO 的非阻塞 IO 技术。
 * 现在需要编写一个客户端程序，用于向该服务器发送请求并接收响应；
 * 以及一个服务端程序，用于接收客户端请求并发送响应。要求必须实现以下功能：
 *
 * •客户端：
 * •创建 Socket，并连接到指定的服务器地址和端口。
 * •发送请求数据到服务器。
 * •接收服务器响应数据，并将其打印到控制台。
 *
 * •服务端
 * •创建服务器 Socket，并绑定到指定端口。
 * •创建 Selector，并将服务器 Socket 注册到 Selector 上。
 * •循环处理客户端请求，包括接收客户端连接、读取客户端请求数据、处理请求、发送响应数据。
 */
public class Server {
    private static final int BUFFER_SIZE = 1024;

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open(); // 创建服务器 Socket
        serverChannel.configureBlocking(false); // 配置为非阻塞模式
        serverChannel.socket().bind(new InetSocketAddress(8080)); // 绑定端口
        Selector selector = Selector.open(); // 创建 Selector
        serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 将服务器 Socket 注册到 Selector 上
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); // 创建缓冲区
        while (true) {
            selector.select(); // 阻塞等待事件
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                if (key.isAcceptable()) { // 处理客户端连接事件
                    SocketChannel channel = serverChannel.accept(); // 接受客户端连接
                    channel.configureBlocking(false); // 配置为非阻塞模式
                    channel.register(selector, SelectionKey.OP_READ); // 将客户端 Channel 注册到 Selector 上
                } else if (key.isReadable()) { // 处理客户端读事件
                    SocketChannel channel = (SocketChannel) key.channel();
                    buffer.clear(); // 清空缓冲区
                    int bytesRead = channel.read(buffer); // 读取客户端请求数据
                    if (bytesRead == -1) { // 如果客户端关闭了连接，则取消注册该 Channel
                        key.cancel();
                        channel.close();
                        continue;
                    }
                    if (buffer.position() >= BUFFER_SIZE) { // 如果缓冲区已满，则处理请求
                        buffer.flip(); // 翻转缓冲区，准备读取数据
                        String request = new String(buffer.array(), 0, buffer.limit());
                        String response = handleRequest(request); // 处理请求
                        buffer.clear(); // 清空缓冲区，准备写入数据
                        buffer.put(response.getBytes());
                        buffer.flip(); // 翻转缓冲区，准备写入数据
                        channel.register(selector, SelectionKey.OP_WRITE); // 注册写事件
                    }
                } else if (key.isWritable()) { // 处理客户端写事件
                    SocketChannel channel = (SocketChannel) key.channel();
                    channel.write(buffer); // 写入响应数据到客户端
                    if (!buffer.hasRemaining()) { // 如果数据已全部写入，则取消注册写事件
                        buffer.clear(); // 清空缓冲区
                        channel.register(selector, SelectionKey.OP_READ); // 注册读事件
                    }
                }
            }
        }
    }

    private static String handleRequest(String request) {
        // 处理请求的逻辑
        return "Response: " + request;
    }
}